package cn.jcet.common.aspect;

import cn.jcet.common.cache.CachePool;
import cn.jcet.module.bus.domain.Customer;
import cn.jcet.module.bus.domain.Goods;
import cn.jcet.module.bus.domain.Provider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import org.thymeleaf.expression.Ids;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
@EnableAspectJAutoProxy
public class BusinessCacheAspect {

    //日志
    private Log log = LogFactory.getLog(BusinessCacheAspect.class);

    // 声明一个缓存容器
    private static Map<String, Object> CACHE_CONTAINER = CachePool.CACHE_CONTAINER;

    public static Map<String, Object> getCACHE_CONTAINER() {

        return CACHE_CONTAINER;
    }

    // 声明切面表达式
    private static final String POINTCUT_CUSTOMER_ADD = "execution(* cn.jcet.module.bus.service.impl.CustomerServiceImpl.save(..))";
    private static final String POINTCUT_CUSTOMER_UPDATE = "execution(* cn.jcet.module.bus.service.impl.CustomerServiceImpl.updateById(..))";
    private static final String POINTCUT_CUSTOMER_GET = "execution(* cn.jcet.module.bus.service.impl.CustomerServiceImpl.getById(..))";
    private static final String POINTCUT_CUSTOMER_DELETE = "execution(* cn.jcet.module.bus.service.impl.CustomerServiceImpl.removeById(..))";
    private static final String POINTCUT_CUSTOMER_BATCHDELETE = "execution(* cn.jcet.module.bus.service.impl.CustomerServiceImpl.removeByIds(..))";

    private static final String CACHE_CUSTOMER_PROFIX = "customer:";


    @Around(value = POINTCUT_CUSTOMER_GET)
    public Object cacheCustomerGet(ProceedingJoinPoint joinPoint){
        try {
            Integer cId = (Integer) joinPoint.getArgs()[0];
            Customer result1 = (Customer) getCACHE_CONTAINER().get(CACHE_CUSTOMER_PROFIX + cId);
            if(result1 != null){
                log.info("已从缓存里面找到客户对象" + CACHE_CUSTOMER_PROFIX + result1);
                return result1;
            }else {
                Customer result2 = (Customer) joinPoint.proceed();
                getCACHE_CONTAINER().put(CACHE_CUSTOMER_PROFIX+result2.getId(),result2);
                log.info("未从缓存中获取，放到数据库中查询" + CACHE_CUSTOMER_PROFIX + result2);
                return result2;
            }
        }catch (Throwable throwable){

        }
        return null;
    }


    /**
     * 添加
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_CUSTOMER_ADD)
    public Object cacheCustomerAdd(ProceedingJoinPoint joinPoint){
        try{
            //获取第一个参数
           Customer object = (Customer) joinPoint.getArgs()[0];
           Boolean isSuccess = (Boolean) joinPoint.proceed();
           if(isSuccess){
                getCACHE_CONTAINER().put(CACHE_CUSTOMER_PROFIX+object.getId(),object);
           }
           return isSuccess;
        }catch (Throwable throwable){

        }
        return null;
    }

    /**
     * 修改
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_CUSTOMER_UPDATE)
    public Object cacheCustomerUpdate(ProceedingJoinPoint joinPoint){
        try {
            //获取参数
            Customer object = (Customer) joinPoint.getArgs()[0];
            Boolean isSuccess= (Boolean) joinPoint.proceed();
            if(isSuccess){
                Customer customer = (Customer) getCACHE_CONTAINER().get(CACHE_CUSTOMER_PROFIX + object.getId());
                if(customer ==null){
                    customer = new Customer();
                }
                BeanUtils.copyProperties(object,customer);
                getCACHE_CONTAINER().put(CACHE_CUSTOMER_PROFIX+customer.getId(),customer);
            }
            return isSuccess;
        }catch (Throwable throwable){

        }
        return null;
    }

    /**
     * 删除
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_CUSTOMER_DELETE)
    public Object cacheCustomerDelete(ProceedingJoinPoint joinPoint){
        try {
           Integer cid = (Integer) joinPoint.getArgs()[0];
           Boolean isSuccess = (Boolean) joinPoint.proceed();
           if(isSuccess){
               getCACHE_CONTAINER().remove(CACHE_CUSTOMER_PROFIX+cid);
           }
           return isSuccess;
        }catch (Throwable throwable){

        }
        return null;
    }

    @Around(value =POINTCUT_CUSTOMER_BATCHDELETE )
    public Object cacheCustomerBatchDelete(ProceedingJoinPoint joinPoint){
        try {
            Collection<Serializable> listIds = (Collection<Serializable>) joinPoint.getArgs()[0];
            Boolean isSuccess = (Boolean) joinPoint.proceed();
            if(isSuccess){
                for (Serializable ids : listIds){
                    log.info("批量删除缓存ids"+getCACHE_CONTAINER()+ids);
                    getCACHE_CONTAINER().remove(CACHE_CUSTOMER_PROFIX+ids);
                }
            }
            return isSuccess;
        }catch (Throwable throwable){

        }
        return null;
    }

    // 声明切面表达式
    private static final String POINTCUT_PROVIDER_ADD = "execution(* cn.jcet.module.bus.service.impl.ProviderServiceImpl.save(..))";
    private static final String POINTCUT_PROVIDER_UPDATE = "execution(* cn.jcet.module.bus.service.impl.ProviderServiceImpl.updateById(..))";
    private static final String POINTCUT_PROVIDER_GET = "execution(* cn.jcet.module.bus.service.impl.ProviderServiceImpl.getById(..))";
    private static final String POINTCUT_PROVIDER_DELETE = "execution(* cn.jcet.module.bus.service.impl.ProviderServiceImpl.removeById(..))";
    private static final String POINTCUT_PROVIDER_BATCHDELETE = "execution(* cn.jcet.module.bus.service.impl.ProviderServiceImpl.removeByIds(..))";

    private static final String CACHE_PROVIDER_PROFIX = "provider:";


    /**
     * 获取缓存
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_PROVIDER_GET)
    public Object cacheProviderGet(ProceedingJoinPoint joinPoint){
        try {
            Integer pId = (Integer) joinPoint.getArgs()[0];
            Provider result1 = (Provider) getCACHE_CONTAINER().get(CACHE_PROVIDER_PROFIX +pId);
            if(result1 != null){
                return result1;
            }else {
                Provider result2 = (Provider) joinPoint.proceed();
                getCACHE_CONTAINER().put(CACHE_PROVIDER_PROFIX+result2.getId(),result2);
                return result2;
            }
        }catch (Throwable throwable){

        }
        return null;
    }

    /**
     * 添加
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_PROVIDER_ADD)
    public Object cacheProviderAdd(ProceedingJoinPoint joinPoint){
        try {
            Provider objcet = (Provider) joinPoint.getArgs()[0];
            Boolean isSuccess = (Boolean) joinPoint.proceed();
            if(isSuccess){
                log.info("存入缓存成功"+objcet.getId());
                getCACHE_CONTAINER().put(CACHE_PROVIDER_PROFIX+objcet.getId(),objcet);
            }
            return isSuccess;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 修改
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_PROVIDER_UPDATE)
    public Object cacheProviderUpdate(ProceedingJoinPoint joinPoint){
        try {
            Provider providerVo = (Provider) joinPoint.getArgs()[0];
            Boolean isSuccess = (Boolean) joinPoint.proceed();
            if(isSuccess){
                Provider provider = (Provider) getCACHE_CONTAINER().get(CACHE_PROVIDER_PROFIX + providerVo.getId());
                if(null == provider){
                    provider = new Provider();
                }
                BeanUtils.copyProperties(providerVo,provider);
                getCACHE_CONTAINER().put(CACHE_PROVIDER_PROFIX + provider.getId(), provider);
            }
            return isSuccess;
        }catch (Throwable throwable){

        }
        return null;
    }

    /**
     * 删除
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_PROVIDER_DELETE)
    public Object cacheProviderDelete(ProceedingJoinPoint joinPoint){
        try {
            Integer pid = (Integer) joinPoint.getArgs()[0];
            Boolean isSuccess = (Boolean) joinPoint.proceed();
            if(isSuccess){
                getCACHE_CONTAINER().remove(CACHE_PROVIDER_PROFIX+pid);
            }
            return isSuccess;
        }catch (Throwable throwable){

        }
        return null;
    }

    /**
     * 批量删除
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_PROVIDER_BATCHDELETE)
    public Object cacheProviderBatchDelete(ProceedingJoinPoint joinPoint){
        try {
            @SuppressWarnings("unchecked")
           Collection<Serializable> listIds = (Collection<Serializable>) joinPoint.getArgs()[0];
           Boolean isSuccess = (Boolean) joinPoint.proceed();
           if(isSuccess){
               for (Serializable ids : listIds){
                   getCACHE_CONTAINER().remove(CACHE_PROVIDER_PROFIX+ids);
               }
           }
           return isSuccess;
        }catch (Throwable throwable){

        }
        return null;
    }


    //商品数据的缓存 声明切面表达式
    private static final String POINTCUT_GOODS_ADD = "execution(* cn.jcet.module.bus.service.impl.GoodsServiceImpl.save(..))";
    private static final String POINTCUT_GOODS_UPDATE = "execution(* cn.jcet.module.bus.service.impl.GoodsServiceImpl.updateById(..))";
    private static final String POINTCUT_GOODS_GET = "execution(* cn.jcet.module.bus.service.impl.GoodsServiceImpl.getById(..))";
    private static final String POINTCUT_GOODS_DELETE = "execution(* cn.jcet.module.bus.service.impl.GoodsServiceImpl.removeById(..))";

    private static final String CACHE_GOODS_PROFIX = "goods:";

    /**
     * 获取
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_GOODS_GET)
    public Object cacheGoodsGet(ProceedingJoinPoint joinPoint){
        try {
            Integer gid = (Integer) joinPoint.getArgs()[0];
            Goods result1 = (Goods) getCACHE_CONTAINER().get(CACHE_GOODS_PROFIX + gid);
            if(result1 != null){
                return result1;
            }else {
                Goods result2 = (Goods) joinPoint.proceed();
                getCACHE_CONTAINER().put(CACHE_GOODS_PROFIX+result2.getId(),result2);
                return result2;
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 添加
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_GOODS_ADD)
    public Object cacheGoodsAdd(ProceedingJoinPoint joinPoint){
        try {
            Goods goods = (Goods) joinPoint.getArgs()[0];
            Boolean isSuccess = (Boolean) joinPoint.proceed();
            if (isSuccess){
                getCACHE_CONTAINER().put(CACHE_GOODS_PROFIX+goods.getId(),goods);
            }
            return isSuccess;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 修改
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_GOODS_UPDATE)
    public Object cacheGoodsUpdate(ProceedingJoinPoint joinPoint){
        try {
            Goods goodsVo= (Goods) joinPoint.getArgs()[0];
            Boolean isSuccess = (Boolean) joinPoint.proceed();
            if(isSuccess){
                Goods goods = (Goods) getCACHE_CONTAINER().get(CACHE_GOODS_PROFIX + goodsVo.getId());
                if(null == goods){
                    goods = new Goods();
                }
                BeanUtils.copyProperties(goodsVo,goods);
                getCACHE_CONTAINER().put(CACHE_GOODS_PROFIX+goods.getId(),goods);
            }
            return isSuccess;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 删除
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_GOODS_DELETE)
    public Object cacheGoodsDelete(ProceedingJoinPoint joinPoint) throws Throwable {
        Integer pid = (Integer) joinPoint.getArgs()[0];
        Boolean isSuccess = (Boolean) joinPoint.proceed();
        if (isSuccess) {
            getCACHE_CONTAINER().remove(CACHE_GOODS_PROFIX+pid);
        }
        return isSuccess;
    }

}